
import _ from 'lodash';
import { FilterXSS } from 'xss';
/**
 * 获取 location hash 参数
 * @param {string} variable 参数名
 * @returns {string} 参数值
 */
export const getQueryVariable = (variable) => {
    const query = window.location.hash.split('?');

    if (query.length < 2) {
        return '';
    }

    const vars = query[1].split('&');

    // eslint-disable-next-line @typescript-eslint/prefer-for-of
    for (let i = 0; i < vars.length; i++) {
        const pair = vars[i].split('=');
        if (pair[0] === variable) {
            return decodeURI(pair[1]);
        }
    }
    return '';
};

/**
 * 滚动至指定dom底部
 */
export const scrollToBottom = (sDom, sTop) => {
    if (!sDom) return;

    sDom.scrollTo({
        top: sTop
        // behavior: 'smooth'
    });
};

/**
 * 是否移动端
 */
export const isMobile = () => {
    const matchMobile = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
    if (matchMobile) return !!matchMobile.length;
    return false;
};

/**
 * 数组去重
 */
export const arrayUnique = (arr, replaceKey, holdKey) => {
    let temp = {};

    return arr.reduce((prev, cur) => {
        if (!temp[cur[replaceKey]]) {
            temp[cur[replaceKey]] = {index: prev.length};
            prev.push(cur);
        } else {
            const oldItem = temp[cur[replaceKey]];
            cur[holdKey] = oldItem[holdKey];
            prev.splice(oldItem['index'], 1, cur);
        }

        return prev;
    }, []);
};

export const generateRequestId = (length = 10) => {
    const data =
        ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
            'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
            'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
            's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    let nums = '';
    for (let i = 0; i < length; i++) {
        const r = parseInt(Math.random() * 61, 10);
        nums += data[r];
    }
    return nums + '-' + parseInt(Math.random() * 10000000000, 10);
};

function escapeHtml (str) {
    return str.replace(/[&<>"'/]/g, function (match) {
        return {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#39;',
            '/': '&#x2F;'
        }[match];
    });
}

export const escapeUserInput = (input) => {
    const parts = input.split(/(<script[^>]*>.*?<\/script>|<[^>]*>)/gi);
    return parts.map(part => {
        if (part.startsWith('<script')) {
            return escapeHtml(part);
        } else if (part.startsWith('<')) {
            return escapeHtml(part);
        } else {
            return part;
        }
    }).join('');
};

export const isJSON = (data) => {
    try {
        JSON.parse(data);
        return true;
    } catch (error) {
        return false;
    }
};
export const getClarifyQuestion = ({ content: markdownText = '', reply_method }) => {
    if (reply_method !== 15) return {};
    const pattern = /\[.*?\]\(\)/;

    // 查找第一个链接的位置
    const match = markdownText.match(pattern);
    let content = '';

    if (match) {
    // 获取第一个链接之前的内容
        content = markdownText.slice(0, match.index);
    } else {
        console.log('没有找到链接');
    }

    const reg = new RegExp(/\[([^\]]+)\]\(\)/g);
    let matches;
    const results = [];
    while ((matches = reg.exec(markdownText)) !== null) {
        results.push(matches[1]); // matches[1] 是链接文本
    }
    return {
        content,
        clarifyResults: results
    };
};
export const isEmpty = (value) => {
    // 检查 null 和 undefined
    if (value == null) {
        return true;
    }

    // 检查空字符串
    if (typeof value === 'string' && value.trim() === '') {
        return true;
    }

    // 检查空对象或空数组
    if (typeof value === 'object' && Object.keys(value).length === 0) {
        return true;
    }

    // 如果都不是，则返回 false
    return false;
};
export const getLastNum = (num) => {
    return String(num)[String(num).length - 1];
};
export const xssHtmlOptions = {
    css: false,
    // whiteList: {
    // ...whiteList,
    // a: ['class', 'style', 'target', 'data-link-url', 'rel', 'href', 'data-link-url'],
    img: ['class', 'style', 'alt'],
    // audio: ['class', 'style', 'controls', 'controlsList', 'src'],
    // video: ['class', 'style', 'controls', 'width', 'height', 'webkit-playsinline', 'playsinline', 'x5-playsinline', 'poster', 'src'],
    // p: ['class', 'style'],
    // strong: ['class', 'style'],
    // span: ['contenteditable'],
    // div: ['class', 'style', ''],
    // },
    // 文档地址：https://www.npmjs.com/package/xss
    onTagAttr (tag, name, value, isWhiteAttr) {
        if (tag.indexOf('_') !== -1) {
            // 如果包含下划线，则认为是自定义标签，放过
            return `${name}="${value}"`;
        }
        const tagIgnore = ['div', 'span', 'strong', 'p', 'mark'];
        if (tagIgnore.includes(tag)) {
            // do not filter its attributes
            const blockAttrsReg = /^on/;
            if (!blockAttrsReg.test(name)) {
                return `${name}="${value}"`;
            }
        }
        const tagAttrIgnore = ['class', 'style'];
        if (tagAttrIgnore.includes(name)) {
            return `${name}="${value}"`;
        }
        // 自定义属性省略
        const aTagAttrIgnore = ['rel', 'data-link-url'];
        if (tag === 'a' && aTagAttrIgnore.includes(name)) {
            return `${name}="${value}"`;
        }
        const videoTagAttrIgnore = [
            'rel',
            'webkit-playsinline',
            'x5-playsinline',
            'title',
            'size',
            'format'
        ];
        if (tag === 'video' && videoTagAttrIgnore.includes(name)) {
            return `${name}="${value}"`;
        }
        const audioTagAttrIgnore = [
            'controls',
            'controlslist',
            'id',
            'speed',
            'title',
            'size',
            'format',
            'data-duration-ms'
        ];
        if (tag === 'audio' && audioTagAttrIgnore.includes(name)) {
            return `${name}="${value}"`;
        }
        const imgTagAttrIgnore = ['alt', 'data-value'];
        if (tag === 'img' && imgTagAttrIgnore.includes(name)) {
            return `${name}="${value}"`;
        }
        // if (!isWhiteAttr) {
        //   return '';
        // }
    }
};
export const xssHandlerProcess = (value) => {
    const xssHandler = new FilterXSS(xssHtmlOptions);
    return xssHandler.process(value);
};
export const imgStyle = (num) => {
    let color = [
        '#1492FF', '#1492FF',
        '#0FB87F', '#0FB87F',
        '#FF8345', '#FF8345',
        '#6A45E5', '#6A45E5',
        '#4A70FF', '#4A70FF'
    ];
    let border = [
        '#D0EFFF', '#D0EFFF',
        '#C0EBD7', '#C0EBD7',
        '#FFEBDA', '#FFEBDA',
        '#E2D5F8', '#E2D5F8',
        '#DBE8FF', '#DBE8FF'
    ];
    let background = [
        '#ECF9FF', '#ECF9FF',
        '#E6F8EF', '#E6F8EF',
        '#FFF8F0', '#FFF8F0',
        '#F4EEFC', '#F4EEFC',
        '#F1F6FF', '#F1F6FF'
    ];
    let index = getLastNum(num);
    return {
        color: color[index],
        border: `0.5px solid ${border[index]}`,
        background: background[index]
    };
};

// let mdStr = "Hello ~ World ~~ Test ~~~";
// console.log(escapeSingleTilde(mdStr));  // 输出: "Hello \~ World ~~ Test ~~~"
export const escapeSingleTilde = (str) => {
    return str.replace(/(^|[^~\\])~([^~]|$)/g, '$1\\~$2');
};

// 如果markdown字符串里的*号如果前后有数字，就在前面加上转义符
export const escapeMarkdownStars = (str) => {
    return str.replace(/([\d+\-/=≈])\*/g, '$1\\*');
};

export const formattedEllipsis = (text, length = 40) => {
    if (Object.prototype.toString.call(text) !== '[object String]') { return; };
    if (text && text.length > length) {
        return text.slice(0, length).slice(0, -3) + '...';
    }
    return text;
};

const matchImageLinks = (text) => {
    const regex = /!\[([^\]]+)\]\(([^)]+)\)/g;
    const matches = [];
    let match;
    while ((match = regex.exec(text)) !== null) {
        matches.push(match[0]);
    }
    return matches;
};
export const replaceLinks = (text) => {
    console.log('【workflow tokens】replaceLinks', text);
    if (!text) return text;
    text = text.replace(/\\([*_()])/g, '$1');
    // text = text.replace(/(?<!<[^>]*)>/g, '\\>');
    // 先把里面的图片保留
    const matchImgs = matchImageLinks(text);
    matchImgs.forEach((i, index) => {
        text = text.replace(i, `IMG_URL${index}`);
    });
    const from = getQueryVariable('from');
    const replaceUrl = from ? '' : `${window.location.protocol}//${window.location.host}/lke#/link-info/redirect?target=`;
    const regex = new RegExp(
        '(\\[([^\\]]+)\\]\\((https?:\\/\\/(?!oaqbot\\.qidian\\.qq\\.com)[^\\s)]+)\\))|(<a\\s+[^>]*href="((?!oaqbot\\.qidian\\.qq\\.com)[^"]+)"[^>]*>(.*?)<\\/a>)',
        'gi'
    );
    text = text.replace(regex, (match, p1, p2, p3, p4, p5, p6) => {
        if (p1 && p2) {
            return `[${p2}](${replaceUrl}${p3})`;
        } else if (p5 && !p5.startsWith('#')) {
            return `<a href="${replaceUrl}${p5}">${p6}</a>`;
        } else {
            return match;
        }
    });
    matchImgs.forEach((i, index) => {
        text = text.replace(`IMG_URL${index}`, i);
    });

    text = escapeSingleTilde(text);

    text = escapeMarkdownStars(text);

    return xssHandlerProcess(text);
};
// 把string变为大写驼峰
export const capitalizedCamelCase = (value) => {
    return _.upperFirst(_.camelCase(value));
};

// 把数据中所有key变为snake_case
export const convertToSnakeCase = (obj) => {
    if (Array.isArray(obj)) {
        return obj.map(v => convertToSnakeCase(v));
    } else if (obj && obj.constructor === Object) {
        let res = {};
        Object.entries(obj).forEach(([key, value]) => {
            res[_.snakeCase(key)] = convertToSnakeCase(value);
        });
        return res;
    } else {
        return obj;
    }
};

// 把数据中所有key和value变为大写驼峰
export const convertToCapitalizedCamelCase = (obj) => {
    if (Array.isArray(obj)) {
        return obj.map(v => convertToCapitalizedCamelCase(v));
    } else if (obj && obj.constructor === Object) {
        let res = {};
        Object.entries(obj).forEach(([key, value]) => {
            res[capitalizedCamelCase(key)] = convertToCapitalizedCamelCase(value);
        });
        return res;
    } else {
        return obj;
    }
};
